// Component.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"

#include <iostream>

class Independent0
{
public:
  int f0()
  {
    return 0;
  }
};

class Independent1
{
public:
  Independent1()
    : n(1)
  {
  }

  int f1()
  {
    return n;
  }

private:
  int n;
};

class Dependent
{
public:
  Dependent(Independent0& I0, Independent1& I1)
    : mI0(I0)
    , mI1(I1)
  {
  }

  void PrintIndependent0()
  {
    using std::cout;
    using std::endl;

    cout << mI0.f0() << endl;
  }

  void PrintIndependent1()
  {
    using std::cout;
    using std::endl;

    cout << mI1.f1() << endl;
  }

private:
  Independent0& mI0;
  Independent1& mI1;
};

template<class CompT>
class StaticComponent
{
public:
  StaticComponent()
  {
  }

  template<class T0>
  StaticComponent(T0& A0)
    : mComp(A0)
  {
  }

  template<class T0, class T1>
  StaticComponent(T0& A0, T1& A1)
    : mComp(A0, A1)
  {
  }

  template<class T0, class T1, class T2>
  StaticComponent(T0& A0, T1& A1, T2& A2)
    : mComp(A0, A1, A2)
  {
  }

  template<class T0, class T1, class T2, class T3>
  StaticComponent(T0& A0, T1& A1, T2& A2, T3& A3)
    : mComp(A0, A1, A2, A3)
  {
  }

  template<class T0, class T1, class T2, class T3, class T4>
  StaticComponent(T0& A0, T1& A1, T2& A2, T3& A3, T4& A4)
    : mComp(A0, A1, A2, A3, A4)
  {
  }

  operator CompT&()
  {
    return mComp;
  }

private:
  private:
  StaticComponent(const StaticComponent&);
  StaticComponent& operator =(const StaticComponent&);


  CompT mComp;
};

template<class CompT>
class DynamicComponent
{
public:
  DynamicComponent()
  {
    mComp = new CompT();
  }

  template<class T0>
  DynamicComponent(T0& A0)
  {
    mComp = new CompT(A0);
  }

  template<class T0, class T1>
  DynamicComponent(T0& A0, T1& A1)
  {
    mComp = new CompT(A0, A1);
  }

  template<class T0, class T1, class T2>
  DynamicComponent(T0& A0, T1& A1, T2& A2)
  {
    mComp = new CompT(A0, A1, A2);
  }

  template<class T0, class T1, class T2, class T3>
  DynamicComponent(T0& A0, T1& A1, T2& A2, T3& A3)
  {
    mComp = new CompT(A0, A1, A2, A3);
  }

  template<class T0, class T1, class T2, class T3, class T4>
  DynamicComponent(T0& A0, T1& A1, T2& A2, T3& A3, T4& A4)
  {
    mComp = new CompT(A0, A1, A2, A3, A4);
  }

  ~DynamicComponent()
  {
    delete mComp;
  }

  operator CompT&()
  {
    return *mComp;
  }

private:
  DynamicComponent(const DynamicComponent&);
  DynamicComponent& operator =(const DynamicComponent&);

  CompT* mComp;
};

class Composite
{
public:
  Composite()
    : mD(mI0, mI1)
  {
  }

private:
  StaticComponent<Independent0> mI0;
  StaticComponent<Independent1> mI1;
  StaticComponent<Dependent> mD;

public:

  Independent0& Indepndent0()
  {
    return mI0;
  }

  Independent1& Indepndent1()
  {
    return mI1;
  }

  Dependent& Dependent()
  {
    return mD;
  }
};

int _tmain(int argc, _TCHAR* argv[])
{
  Composite Object;

  Object.Indepndent0().f0();
  Object.Indepndent1().f1();
  Object.Dependent().PrintIndependent0();
  Object.Dependent().PrintIndependent1();
  
	return 0;
}

